<template>
	<!-- 这层div很重要，不能删，是为了解决key值渲染可能导致父级组件refs列表重排的问题 -->
	<div>
		<el-cascader
			ref="cascader"
			:key="cascaderKey"
			:filterable="true"
			placeholder="请选择系列课"
			:show-all-levels="false"
			:options="options"
			:props="props"
			:value="cascaderValue"
			@change="change"
		/>
	</div>
</template>

<script>
	import rcTagApi from "@rc/apis/rc/tag.mjs";

	export default {
		props: {
			/**
			 * 当前的默认的选中值
			 * 1.支持v-model
			 * 2.默认单选，支持传入两种风格  1.[子id] 2.[父id,子id]，注：修改后传出的是[父id,子id]
			 * 3.多选(propsOptions.multiple = true)  1. [子id,子id,...]  2. [[父id,子id], [父id,子id]...]，注：修改后传出的是第二种格式
			 */
			value: {
				type: Array,
				default: () => []
			},
			// 项目id，必传，为空时无可选内容
			projectId: {
				type: String,
				default: "",
				required: true
			},
			// cascader组件的props参数，会与组件配置的进行合并 https://element.eleme.cn/#/zh-CN/component/cascader
			propsOptions: {
				type: Object,
				default: () => {}
			}
		},
		data() {
			return {
				props: {
					// 级联框基础配置
					value: "id",
					label: "name"
				},
				cascaderKey: 1, // 为了避免切换数据源报错，让组件重新渲染
				options: [],
				flatOptions: [] // 扁平化的列表
			};
		},
		computed: {
			cascaderValue() {
				//经过处理的，符合cascader组件格式需求标准的value
				let result = [];
				if (this.props.multiple) {
					// 多选类型
					result = this.value.map((i) => {
						if (Array.isArray(i)) {
							// 父级子级全有的多选[[],[]]
							return i;
						} else {
							// 只有子级的多选[子id1,子id2]
							const findItem = this.flatOptions.find((i2) => i2.id === i);
							return findItem ? findItem.ids : [];
						}
					});
					result = result.filter((i) => i); // 过滤掉为null的未匹配上的id
					// 如果传来的回显数据与渲染数据排序方式不一致，cascader组件进行标签删除时会删除错误的对象
					result.sort((a, b) => {
						const aIndex = this.flatOptions.findIndex((i) => i.id === a[a.length - 1]);
						const bIndex = this.flatOptions.findIndex((i) => i.id === b[b.length - 1]);
						return aIndex - bIndex;
					});
				} else {
					// 单选类型
					const childrenId = this.value[this.value.length - 1];
					const findItem = this.flatOptions.find((i) => i.id === childrenId);
					result = findItem ? findItem.ids : [];
				}
				return result;
			}
		},
		watch: {
			projectId: {
				handler(val) {
					this.cascaderKey++;
					if (!val) {
						this.options = [];
						return;
					}
					// 更新列表数据
					rcTagApi.queryCoursesTreeList({
						data: { projectId: val },
						success: (data) => {
							this.options = data.map((i) => ({
								...i,
								id: i.teachRangeCode,
								name: i.teachRangeName,
								children: i.seriesCourses
							}));
							// 扁平化的递归函数
							const flatFun = (arr, item, ids) => {
								arr.push({
									id: item.id,
									name: item.name,
									ids: [...ids, item.id] // 父子id集合
								});
								if (item.children && item.children.length) {
									item.children.forEach((item2) => {
										flatFun(arr, item2, [...ids, item.id]);
									});
								}
							};
							this.options.forEach((item2) => {
								flatFun(this.flatOptions, item2, []);
							});
						}
					});
				},
				immediate: true
			}
		},
		methods: {
			change(data) {
				this.$emit("input", data);
				this.$emit("change", data);
			},
			api_getCheckedNodes() {
				return this.$refs.cascader.getCheckedNodes();
			}
		},
		created() {
			// 合并配置
			this.props = { ...this.props, ...this.propsOptions };
		}
	};
</script>

<style scoped lang="less">
	/deep/ .el-cascader {
		width: 100%;
	}
	/deep/ .el-cascader__tags .el-tag {
		height: 23px;
		line-height: 23px;

		.el-icon-close {
			top: 1px;
		}
	}
</style>
